<?php

namespace app\devices\service;

use think\admin\Service;
use think\App;
use think\cache\driver\Redis;

/**
 * 设备数据服务
 * Class DevicesService
 * @package app\devices\service
 */
class DevicesService extends Service
{
    protected $redis;
    protected $box_types = [1=>'大柜', 2=>'中柜', 3=>'小柜'];
    protected $device_types = [1=>'扫码', 2=>'人脸'];
    protected $fee_types = [3=>'按时', 2=>'按次', 1=>'免费'];

    public function __construct(App $app)
    {
        $this->redis = new Redis();
        parent::__construct($app);
    }

    /**
     * 计算两点地理坐标之间的距离
     * @param Decimal $longitude1 起点经度
     * @param Decimal $latitude1 起点纬度
     * @param Decimal $longitude2 终点经度
     * @param Decimal $latitude2 终点纬度
     * @param Int   $unit    单位 1:米 2:公里
     * @param Int   $decimal  精度 保留小数位数
     * @return Decimal
     */
    function getDistance($longitude1, $latitude1, $longitude2, $latitude2, $unit=2, $decimal=2){

        $EARTH_RADIUS = 6370.996; // 地球半径系数
        $PI = 3.1415926;

        $radLat1 = $latitude1 * $PI / 180.0;
        $radLat2 = $latitude2 * $PI / 180.0;

        $radLng1 = $longitude1 * $PI / 180.0;
        $radLng2 = $longitude2 * $PI /180.0;

        $a = $radLat1 - $radLat2;
        $b = $radLng1 - $radLng2;

        $distance = 2 * asin(sqrt(pow(sin($a/2),2) + cos($radLat1) * cos($radLat2) * pow(sin($b/2),2)));
        $distance = $distance * $EARTH_RADIUS * 1000;

        if($unit==2){
            $distance = $distance / 1000;
        }

        return round($distance, $decimal);

    }

    /**
     * 设置取件码
     * @param $data
     * @param array $map
     * @return bool|int|string
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException\
     */
    function setPickUpCode($data, $map=[]){
        $map = $map?$map:$data;
        unset($map['code']);
        $code = $this->app->db->name("jcg_device_pickupcode")->where($map)->find();
        if($code){
            if($code['code']==$data['code'] && $code['order_id']==$data['order_id']){
                return true;
            }
            $data['used'] = 1;
            $res = $this->app->db->name("jcg_device_pickupcode")->where('id', $code['id'])->update($data);
        }else{
            $res = $this->app->db->name("jcg_device_pickupcode")->insert($data);
        }
        return $res;
    }

    /**
     * 获取订单对应的取件码
     * @param $order_ids
     * @return array
     */
    function getPickUpCodes($order_ids){
        return $this->app->db->name("jcg_device_pickupcode")->where("order_id", "in", $order_ids)->column("mobile, code", "order_id");
    }

    /**
     * 更新取件码状态
     * @param $map
     * @return int
     * @throws \think\db\exception\DbException
     */
    function usePickUpCode($map){
        $code = $this->app->db->name("jcg_device_pickupcode")->order("id DESC")->where($map)->find();
        if($code && $code['used']){
            return 1;
        }else if($code){
            return $this->app->db->name("jcg_device_pickupcode")->where($map)->update(['used'=>1]);
        }else{
            return 1;
        }
    }

    /**
     * 获取设备信息
     * @param int $id
     * @param int $device_id
     * @return array|mixed|\think\Model|null
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    function getDevice($id=0, $device_id=0){
        if($id){
            $device = $this->redis->get("device".$id);
            $map['id'] = $id;
        }else if($device_id){
            $device = $this->redis->get("device".$device_id);
            $map['device_id'] = $device_id;
        }else{
            return [];
        }
        if(!$device){
            $device = $this->app->db->name("jcg_devices")->where($map)->find();
            if($device){
                $this->redis->set("device".($id?$id:$device_id), $device, 300);
            }
        }
        return $device;
    }

    /**
     * 获取柜点
     * @param int|array $id
     * @return array
     */
    function getStore($id){
        if(!is_array($id)){
            $store = $this->redis->get("Store".$id);
            if($store){
                return $store;
            }
        }
        $map[] = is_array($id)?['id', 'in', $id]:['id', '=', $id];
        $stores = $this->app->db->name("jcg_store")->where($map)->column("points, name, start_hours, end_hours, area, address, contact_number, store_img, bus_hours, share_ratio, is_msg, is_code, appid, show_vip", "id");
        if(!is_array($id) && $stores){
            $this->redis->set("Store".$id, $stores[$id], 300);
        }
        if(!$stores){
            return [];
        }

        return is_array($id) ? $stores : $stores[$id];
    }

    /**
     * 获取所有柜点提前1小时的结束营业时间
     * @return array
     */
    function getStoresEndHours(){
        return $this->app->db->name("jcg_store")->where("bus_hours","0")->whereRaw("hour(end_hours)=".(date("H")+1))->column("end_hours", "id");
    }

    /**
     * 获取所有柜点当前小时的结束营业时间
     * @return array
     */
    function getStoresEndHours2(){
        return $this->app->db->name("jcg_store")->where("bus_hours","0")->whereRaw("hour(end_hours)=".(date("H")))->column("end_hours", "id");
    }

    /**
     * 根据坐标计算距离
     * @param array $data
     * @param string $distance
     */
    function buildStoreData(array &$data = [], $distance=''){
        if($distance){
            $distance = str_replace("，",",", $distance);
            $distance = explode(",",$distance);
        }

        $kil = [];
        foreach ($data as &$row){
            $store_points = $row['points']??"";
            $row['kilometre'] = 0;
            if($store_points && $distance){
                $store_points = str_replace("，",",", $store_points);
                $store_points = explode(",", $store_points);

                $kilometre = $this->getDistance($distance[1], $distance[0], $store_points[1], $store_points[0]);
                $kil[] = $kilometre;
                $row['kilometre'] = $kilometre;
            }

            $row['address'] = $row['area']." ".($row['address']??'');
            unset($row['area']);
            unset($row['points']);
        }
        if($distance && $data && $kil){
            array_multisort($kil, SORT_ASC, $data);
        }

    }

    /**
     * 设备信息编辑
     * @param array $data
     */
    function buildItemData(array &$data = []){
        $d_ids = array_column($data, 'd_id');

        $box_counts = BoxService::instance()->getDevicesBoxNum($d_ids);

        foreach ($data as &$row){
            $row['box_num'] = $box_counts[$row['d_id']]??0;
        }
    }

    /**
     * 商户端设置柜子相关信息
     * @param array $data
     * @param array $user
     */
    function getBoxInfo(array &$data = [], array $user=[]){
        $order_list = [];
        if(($user['stores']??[])){
            $map[] = ['status', '=', 1];
            $map[] = ['store_id', 'in', $user['stores']];
            $map[] = ['out_times', '=', 1];
            $order_list = OrderService::instance()->getOutTimeNum($map);
        }
        $d_ids = array_column($data, 'd_id');
        $box_counts = BoxService::instance()->getBoxNums($d_ids);
        foreach ($data as &$row){
            $boxs = $box_counts[$row['d_id']]??[];
            $row['all_num'] = $boxs['all_num']??0;
            $row['use_num'] = $boxs['use_num']??0;
            $row['unlock_num'] = $boxs['unlock_num']??0;
            $row['out_num'] = isset($order_list[$row['d_id']])?$order_list[$row['d_id']]:0;
            $row['status_title'] = $row['online']==1?'在线':'离线';
            if($row['status']!=1){
                $row['status_title'] = '停用';
            }
            unset($row['status'], $row['online'], $row['device_id']);
        }

        $user['devices'] = $this->getStoresDevices($user['stores']);
        $this->redis->set("sys_store_user_".$user['id'], $user, 7200);
    }

    /**
     * 获取费用详情
     * @param $id
     * @return array|\think\Model|null
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    function getDeviceFee($id){
        return $this->app->db->name("jcg_device_fee")->field("fee_type, fee_detail, summary")->where("id", $id)->find();
    }

    function feeBuild(&$fee){
        $details = json_decode($fee['fee_detail'], true);

        $rule = [];
        for($box_type=1; $box_type<4; $box_type++){
            $row['name'] = $this->box_types[$box_type]??'';
            if($fee['fee_type']==1){

            }else if($fee['fee_type']==2){
                //按次
                $row['price'] = $details[($box_type-1)*5+1];
                $row['overdue_expenses'] = $details[($box_type-1)*5+3];
                $row['max_day'] = $details[($box_type-1)*5+2];
            }else if($fee['fee_type']==3){
                //按时
//                $row['price'] = $details[($box_type-1)*5+2];
//                $row['']$details[($box_type-1)*5+3].'元';
//                        $box_type.$details[($box_type-1)*5+2].'元/小时，1天封顶'.
//                        '结束订单后，余额秒退回'
//                    ],
//                    'price_label'=>'预付金额',
//                    'price_describe'=>'按时长收费，多退少补，结束订单后，余额秒退回'
//                ];
            }
            $rule[] = $row;
        }
        $fee['fee_type'] = $this->fee_types[$fee['fee_type']];
        $fee['rule'] = $fee['summary']?$fee['summary']:$rule;
        unset($fee['fee_detail']);
    }

    /**
     * 二维码扫码选择设备ID
     * @param $user_id
     * @param $device_id
     * @return bool|int|string
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function setDeviceUser($user_id, $device_id){
        $d_id = 0;
        if(is_int($device_id)){
            $d_id = $device_id;
        }
        $device = $this->getDevice($d_id, $device_id);
        $res = false;
        if($device){
            $d_user = $this->app->db->name("jcg_device_user")->where('user_id', $user_id)->find();
            if($d_user['id']){
                $res = $this->app->db->name("jcg_device_user")->where("id", $d_user['id'])->update(['user_id'=>$user_id, 'd_id'=>$device['id']]);
            }else{
                $res = $this->app->db->name("jcg_device_user")->insert(['user_id'=>$user_id, 'd_id'=>$device['id']]);
            }
        }
        return $res;
    }

    /**
     * 获取二维码扫码设备ID
     * @param $user_id
     * @return bool|int|string
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function getDeviceUser($user_id){
        return $this->app->db->name("jcg_device_user")->where('user_id', $user_id)->find();
    }

    /**
     * 获取柜点所有设备的ID
     * @param $store_id
     * @return array
     */
    public function getStoreDId($store_id){
        return $this->app->db->name("jcg_devices")->where('store_id', $store_id)->column("id");
    }

    public function getStoresDevices($store_ids){
        return $this->app->db->name("jcg_devices")->where('store_id', 'in', $store_ids)->column("device_name, device_id", 'id');
    }
}